package com.powergame.engine;

import com.jme3.collision.CollisionResults;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Mesh;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.VertexBuffer.Type;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Sphere;
import com.jme3.system.AppSettings;
import com.jme3.ui.Picture;
import com.jme3.util.BufferUtils;
import com.powergame.controls.CameraControl;
import com.powergame.main.PowerGame2DMain;
import com.powergame.model.Jeu;
import com.powergame.model.Joueur;
import com.powergame.model.Piece;
import com.powergame.model.Secteur;
import java.awt.Point;
import java.awt.Polygon;
import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * PowerGameDisplayControl.java
 *
 * Se charge d'afficher la scence complète du jeu
 *
 * @author ToF
 */
public class PowerGameDisplayEngine implements ActionListener {

    /** Objet JME */
    private PowerGame2DMain application = null;
    
    private AppSettings settings = null;
    
    /** Le modele de données à afficher */
    private Jeu jeu = null;
    
    // éléments de la scene 
    private Spatial sPlateau = null;
    
    private Geometry mark = null; 
    
    private String message = "";
    
    private Piece pieceSelected = null;
    
    public PowerGameDisplayEngine(PowerGame2DMain app, AppSettings settings, Jeu jeu){
        this.application = app;
        this.settings = settings;
        this.jeu = jeu;
        
        init_display();
    }
    
    public void init_display(){
        application.setDisplayFps(false);
        application.setDisplayStatView(false);
        
        // HUD
        /*Picture pic = new Picture("HUD");
        pic.setImage(application.getAssetManager(), "/Interface/HUD.png", true);
        pic.setWidth(settings.getWidth());
        pic.setHeight(settings.getHeight() * 0.2f);
        pic.setPosition(0, 0);
        application.getGuiNode().attachChild(pic);*/
        
        application.getFlyByCamera().setEnabled(false);
        application.getInputManager().setCursorVisible(true);
        
        // Affiche le plateau
        //sPlateau = application.getAssetManager().loadModel("/Models/plateau.j3o");
        sPlateau = new Geometry("Plateau", new Box(Vector3f.ZERO, 112f, 1f, 112f));
        Material mat = new Material(application.getAssetManager(), "/Common/MatDefs/Light/Lighting.j3md");
        mat.setTexture("DiffuseMap", application.getAssetManager().loadTexture("/Maps/plateau_final.png"));
        sPlateau.setMaterial(mat); 
        
        sPlateau.setLocalTranslation(Vector3f.ZERO);
        application.getRootNode().attachChild(sPlateau);
         
        Node pieces = new Node("pieces");
        application.getRootNode().attachChild(pieces);
        
        // Lumières
        DirectionalLight sun = new DirectionalLight();
        sun.setDirection((new Vector3f(0.5f, -0.5f, 0)).normalize());
        sun.setColor(ColorRGBA.White);
        application.getRootNode().addLight(sun);
        
        // Caméra
        application.getCamera().setLocation(new Vector3f(0, 200f, 0));
        application.getCamera().lookAt(Vector3f.ZERO, application.getCamera().getDirection());
        CameraControl camControl = new CameraControl(application.getCamera());
        camControl.registerInput(application.getInputManager());
        camControl.setxMax(200f);
        camControl.setxMin(-200f);
        camControl.setyMax(2000f);
        camControl.setyMin(-2000f);
        camControl.setzMin(-470f);
        camControl.setzMax(470f);
        sPlateau.addControl(camControl);
        
        // Controles clavier/souris
        String[] mapping = {"SELECT","AQUIRE_ON_OFF","AQUIRE_NEXT_POLY", "MOVE", "NV_JOUEUR"};
        application.getInputManager().addMapping("SELECT", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        application.getInputManager().addMapping("MOVE", new MouseButtonTrigger(MouseInput.BUTTON_RIGHT));
        application.getInputManager().addMapping("AQUIRE_ON_OFF", new KeyTrigger(KeyInput.KEY_M));
        application.getInputManager().addMapping("AQUIRE_NEXT_POLY", new KeyTrigger(KeyInput.KEY_N));
        application.getInputManager().addMapping("NV_JOUEUR", new KeyTrigger(KeyInput.KEY_J));
        
        application.getInputManager().addListener(this, mapping);
        
        application.getInputManager().setSimulateKeyboard(false);
    }
    
    public void printText(String text){
         message = text;
    }
    
    public void update(float tpf){
        // Affiche une frame de jeu 
        application.debug.setText(message);
    }
    
    public void onAction(String name, boolean isPressed, float tpf) {
        if(name.equals("SELECT") && isPressed){
            CollisionResults results = new CollisionResults();
            
            Vector2f pos = application.getInputManager().getCursorPosition();
            
            Vector3f wo = application.getCamera().getWorldCoordinates(pos, 0f);
            Vector3f direction = wo.subtractLocal(application.getCamera().getLocation()).normalizeLocal();
            
            Ray ray = new Ray(application.getCamera().getLocation(), direction);
            
            sPlateau.collideWith(ray, results);
            
            if(results.size() > 0){
                Vector3f contact = results.getClosestCollision().getContactPoint();
                
                /*mark.setLocalTranslation(contact);
                application.getRootNode().attachChild(mark);*/
                
                if(application.aquisitionPoints){
                    Secteur secteur = application.mapCreator.current();

                    application.mapCreator.point(new Point((int)contact.x, (int)contact.z));
                    printText("    >" + secteur.getId() + "(" + secteur.getPolygone().npoints + " points): Nouveau point(" + (int)contact.x + ", " + (int)contact.z + ")");
                }else{
                    
                    Secteur secteur = jeu.getPlateau().findSecteurAt((int)contact.x, (int)contact.z);
                    if(secteur != null){
                        printText("    >" + secteur.getId() + " !");
                    }else{
                        printText("    >VIDE à (" + contact.x + ", " + contact.z + "!");
                    }
                }
            }else{
                //application.getRootNode().detachChild(mark);
            }
        }
        /*if(name.equals("AQUIRE_ON_OFF") && !isPressed){
            
            if(application.aquisitionPoints){
                File xml = null;
                try {
                    xml = application.mapCreator.writeXML("secteurs.xml");

                    printText(xml.getAbsolutePath() + " crée !");

                } catch (IOException ex) {
                    Logger.getLogger(PowerGameDisplayEngine.class.getName()).log(Level.SEVERE, null, ex);
                    printText("XML:" + ex.getMessage());
                }
                
            }else{
                application.aquisitionPoints = true;
                Secteur s = application.mapCreator.current();
                if(s != null){
                    printText(s.getId() + " (" + s.getPolygone().npoints + " points enregistrés) (ESPACE pour terminer)");
                }else{
                    printText("Aquisition terminée: Plus de secteurs. M pour ecrire le fichier.");
                }
            }
        }
        if(name.equals("AQUIRE_NEXT_POLY") && !isPressed){
            if(application.aquisitionPoints){
                application.mapCreator.nextSecteur();
                Secteur s = application.mapCreator.current();
                
                if(s != null){
                    printText(s.getId() + " (" + s.getPolygone().npoints + " points enregistrés) (ESPACE pour terminer)");
                }else{
                    printText("Aquisition terminée: Plus de secteurs. M pour ecrire le fichier.");
                }
                
            }else{
                printText("Aquisition terminée: Plus de secteurs. M pour ecrire le fichier.");
            }
        }*/
        if(name.equals("NV_JOUEUR") && !isPressed){
             // On place une pièce du jeu sur l'ile X
            Joueur tof = jeu.getJoueur("ToF");
            Piece soldat = tof.getFabriquePieces().createDestroyer();
            soldat.setPosition(jeu.getPlateau().getSecteur("HQR"));
            //ajoutePiece(soldat);
            
            pieceSelected = soldat;
        }
        
        if(name.equals("MOVE") && !isPressed){
           
            CollisionResults results = new CollisionResults();
            
            Vector2f pos = application.getInputManager().getCursorPosition();
            
            Vector3f wo = application.getCamera().getWorldCoordinates(pos, 0f);
            Vector3f direction = wo.subtractLocal(application.getCamera().getLocation()).normalizeLocal();
            
            Ray ray = new Ray(application.getCamera().getLocation(), direction);
            
            sPlateau.collideWith(ray, results);
            
            if(results.size() > 0){
                Vector3f contact = results.getClosestCollision().getContactPoint();
                Secteur desti = jeu.getPlateau().findSecteurAt((int)contact.x, (int)contact.z);
                
                if(pieceSelected != null){
                    pieceSelected.moveTo(jeu.getPlateau(), desti);
                }
            }
        }
    }
}
